package top.chengdongqing.mishop.order.review

import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Sort
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import top.chengdongqing.mishop.common.exception.BadRequestException
import top.chengdongqing.mishop.common.exception.NotAcceptableException
import top.chengdongqing.mishop.entities.Order
import top.chengdongqing.mishop.entities.OrderReview
import top.chengdongqing.mishop.entities.ProductReview
import top.chengdongqing.mishop.enums.OrderStatus
import top.chengdongqing.mishop.order.review.dto.OrderReviewDTO
import top.chengdongqing.mishop.order.review.dto.ProductReviewDTO
import top.chengdongqing.mishop.order.review.vo.OrderReviewVO
import top.chengdongqing.mishop.order.review.vo.PendingReviewOrderVO
import top.chengdongqing.mishop.order.review.vo.ProductReviewVO
import top.chengdongqing.mishop.repositories.*

@Service
class OrderReviewService(
    private val orderRepository: OrderRepository,
    private val orderReviewRepository: OrderReviewRepository,
    private val productReviewRepository: ProductReviewRepository,
    private val orderItemRepository: OrderItemRepository,
    private val userRepository: UserRepository
) {

    fun getPendingReviewOrders(userId: Int): List<PendingReviewOrderVO> {
        // 仅查询最后十条完成且未评价的订单
        val pageRequest = PageRequest.ofSize(10)
            .withSort(Sort.by(Order::createdAt.name).descending())
        val orders = orderRepository
            .findAllByUserIdAndStatusAndIsReviewedFalse(userId, OrderStatus.COMPLETED, pageRequest)

        return orders.map { PendingReviewOrderVO.of(it) }
    }

    fun getOrderReview(orderId: Int, userId: Int): OrderReviewVO {
        checkOrder(orderId, userId)

        // 查询订单评价信息
        val orderReview = orderReviewRepository.findByOrderIdAndUserId(orderId, userId) ?: OrderReview(
            orderId = orderId,
            userId = userId
        )
        // 查询订单商品列表
        val orderItems = orderItemRepository.findAllByOrderIdGroupByProductId(orderId)
        // 构建订单商品评价vo
        val items = orderItems.map { item ->
            val productReview = productReviewRepository.findByOrderIdAndProductId(orderId, item.productId)
            ProductReviewVO.of(item, productReview)
        }
        return OrderReviewVO.of(orderReview, items)
    }

    private fun checkOrder(orderId: Int, userId: Int): Order {
        val order = orderRepository.findByIdAndUserId(orderId, userId)
            ?: throw BadRequestException("该订单不存在")
        if (order.status != OrderStatus.COMPLETED) {
            throw NotAcceptableException("该订单暂不支持评价")
        }
        return order
    }

    @Transactional
    fun createOrderReview(orderId: Int, orderReviewDTO: OrderReviewDTO, userId: Int) {
        val order = checkOrder(orderId, userId)
        if (orderReviewRepository.existsById(orderId)) {
            throw NotAcceptableException("该订单已评价，暂不支持重复评价")
        }

        // 保存订单评价信息
        val orderReview = OrderReview(
            orderId,
            userId,
            orderReviewDTO.packagingRating,
            orderReviewDTO.speedRating,
            orderReviewDTO.serviceRating,
            orderReviewDTO.content,
            jacksonObjectMapper().writeValueAsString(orderReviewDTO.photoUrls),
            orderReviewDTO.isAnonymous
        )
        orderReviewRepository.save(orderReview)

        // 修改订单评价状态
        order.isReviewed = true
        orderRepository.save(order)
    }

    fun createProductReview(orderId: Int, productId: Int, productReviewDTO: ProductReviewDTO, userId: Int) {
        checkOrder(orderId, userId)
        if (productReviewRepository.existsByOrderIdAndProductId(orderId, productId)) {
            throw NotAcceptableException("该商品已评价，暂不支持重复评价")
        }

        val productReview = ProductReview(
            orderId = orderId,
            productId = productId,
            rating = productReviewDTO.rating,
            content = productReviewDTO.content,
            photoUrls = productReviewDTO.photoUrls?.let {
                jacksonObjectMapper().writeValueAsString(it)
            },
            isAnonymous = productReviewDTO.isAnonymous,
            user = userRepository.findByIdOrNull(userId)
        )
        productReviewRepository.save(productReview)
    }
}